package cn.edu.scau.cmi.crawler.service;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.edu.scau.cmi.ema.controller.base.CmiEmaController;
import cn.edu.scau.cmi.ema.domain.*;
import cn.edu.scau.cmi.ema.service.base.EntityFactoryService;
import cn.edu.scau.cmi.ema.util.CmiSetUtil;
import cn.edu.scau.cmi.ema.util.CmiTimeUtil;
import cn.edu.scau.cmi.front.dao.CmiFoodDAO;

@Service
public class ZhangxinlianEventImportServiceImpl extends CmiEmaController implements ZhangxinlianEventImportService{
	
	@Autowired EntityFactoryService entityFactory;
	@Autowired CmiFoodDAO cmiFoodDAO;
	
	@Override
	public boolean importEvent(Event9zxl event9xls) {
		
//		******** 食物批次的组装：foodtype -> food -> foodbatchfiller | detectmethod -> foodbatch
		
		Food food = buildFood(event9xls);
		if(food == null) {
			System.out.println("Event的Food是空，该数据没有意义");
			event9xls.setImported(false);//没有导入
			event9zxlService.saveEvent9zxl(event9xls);
			return false;
		}
		
		Foodtype foodtype = buildFoodtype(event9xls);
		food.setFoodtype(foodtype);
		food = foodDAO.store(food);
		foodDAO.flush();
		
//		（1）初始化一个event对象
		Event event = entityFactory.initEvent();
		
//		（2）设置默认基本属性：
		event.setAuditTime(Calendar.getInstance());
		event.setAuditor(CmiSetUtil.getFirstInstance(userDAO.findUserByName("张星联")));
		
//		（3）设置基本属性：
		
		event.setName(event9xls.getName());
		event.setDescription(event9xls.getDescription());
		
		
//		张星联老师的这个数据是一个数据，不是字符串。需要修改41960
//		使用xls导入后又变成合适的时间了：
		
		String times = event9xls.getDiscoverydetailtime().replace('/', '-');
		
		event.setDiscoveryTime(CmiTimeUtil.getYMDCalendar(times));//.castZxlDateString2Calendar(event9zxl.getDiscoverydetailtime()));
		
//		（4）设置直接外键
//		也没有主体
		
		Subject subject = buildSubject(event9xls);///subjectDAO.findSubjectById(-2);
		event.setSubject(subject);
		
		User reportor = buildReportor(event9xls);
		event.setReportor(reportor);

		Address discoveryAddress = buildDiscoveryAddress(event9xls);
		if(discoveryAddress == null) {
			discoveryAddress = addressDAO.findAddressById(-2);
		}
		event.setDiscoveryAddress(discoveryAddress);
		
		Address sourceAddress = buildSourceAddress(event9xls);
		if(sourceAddress == null) {
			sourceAddress = addressDAO.findAddressById(-2);
		}
		event.setSourceAddress(sourceAddress);
		
//		被引用部分：多个值，是集合，是纯联系

//		掺假类型，多对多，但是在张星联的数据中，展开有一个
		Set<Adultertype> adultertypes = buildAdultertype(event9xls);
		if(adultertypes!= null && adultertypes.size()>0) {
			event.setAdultertypesForEvent(adultertypes );
		}else {
			System.out.println(event9xls.getNumber() + "的掺假类型是空或者没有找到该掺假类型，该数据没有意义，清重新检查数据！！！");
			return false;
		}
		

		
		Set<Foodbatchfiller> foodbatchfillers = buildFoodbatchfiller(event9xls);
		
//		不能为空，使用-2代替。
		Detectmethod detectmethod = buildDetectmethon(event9xls);
		
		Foodbatch foodbatch = entityFactory.initFoodbatch();
		foodbatch.setFood(food);
		foodbatch.setDetectmethod(detectmethod);
		foodbatch.setUnit(unitDAO.findUnitById(-2));
		foodbatch.setFoodbatchfillersForFoodbatch(foodbatchfillers);
//		TODO !!!!!!日期需要修改，暂时使用当前的值
		Calendar date = Calendar.getInstance();
		
		Calendar foodBatchCalendar = Calendar.getInstance();
		foodBatchCalendar.set(Calendar.YEAR, 2000);
		foodBatchCalendar.set(Calendar.MONTH, 1);
		foodBatchCalendar.set(Calendar.DATE, 1);
		
		
		foodbatch.setDate(date );
		foodbatch.setName(event.getSubject().getName() + event.getName() + "的食物批次");
		foodbatch = foodbatchService.saveFoodbatch(foodbatch);

		event.setFoodbatch(foodbatch);
		
		event = eventService.saveEvent(event);
		
		Eventpunish eventpunish = buildEventpunish(event9xls);
		
		if(eventpunish != null) {
			Calendar punishCalendar = Calendar.getInstance();
			punishCalendar.set(Calendar.YEAR, 2000);
			punishCalendar.set(Calendar.MONTH, 1);
			punishCalendar.set(Calendar.DATE, 1);
			
			eventpunish.setDate(punishCalendar);
			eventpunish.setName(event.getName() + "的处理");
			eventpunish.setPunish(punishDAO.findPunishById(-2));//
			eventpunish.setEvent(event);
			eventpunish = eventpunishService.saveEventpunish(eventpunish);
//			eventpunishs.add(eventpunish);
		}
//		event.setEventpunishsForEvent(eventpunishs);
		
//		有多个掺假环节adulterlink
		Set<Adulterlink> adulterlinks = buildAdulterlink(event9xls);
		for(Adulterlink adulterlink : adulterlinks) {
			Eventadulterlink eventadulterlink = entityFactory.initEventadulterlink();
			eventadulterlink.setEvent(event);
			eventadulterlink.setAdulterlink(adulterlink);
			eventadulterlink = eventadulterlinkService.saveEventadulterlink(eventadulterlink);
		}
		
		Hazard hazard = buildHazard(event9xls);
		Set<Eventhazard> hazards = new HashSet<Eventhazard>();
		if(hazard !=null) {
			Eventhazard eventhazard= entityFactory.iniEventhazard();
			eventhazard.setEvent(event);
			eventhazard.setHazard(hazard);
			hazards.add(eventhazard);
			event.setEventhazardsForEvent(hazards);
		}
		
//		删除已经导入的数据
		event9zxlService.deleteEvent9zxl(event9xls);
		return true;
	}
	
private Hazard buildHazard(Event9zxl event9zxl) {
	Hazard hazard = null;
	String hazardString = event9zxl.getEventhazard();
	if(hazardString ==null || hazardString.trim().equals("")) {
		return hazard;
	}
//	风险也不能自己增加，预定义
	Set<Hazard> hazards = hazardDAO.findHazardByName(hazardString);
	if(hazards.size()>0) {
		hazard = CmiSetUtil.getFirstInstance(hazards);
	}else {
		hazard = hazardDAO.findHazardById(-2);
	}
	return hazard;
	}

	//	不添加，只查找。
	private Set<Adulterlink> buildAdulterlink(Event9zxl event9zxl) {
		Set<Adulterlink> adulterlinks = new HashSet<Adulterlink>();
//		String adulterlinkString  = event9zxl.getAdulterlink();
		String[] adulterlinkStrings = event9zxl.getAdulterlink().split("、");
		for(String adulterlinkString : adulterlinkStrings) {
			Set<Adulterlink> as = adulterlinkDAO.findAdulterlinkByName(adulterlinkString);
			adulterlinks.addAll(as);
		}
		return adulterlinks;
	}

	private Detectmethod buildDetectmethon(Event9zxl event9zxl) {
		Detectmethod detectmethod = null;
		String detectmethodString = event9zxl.getDetectmethod();
		if(detectmethodString == null || detectmethodString.trim().equals("")) {
			return detectmethodDAO.findDetectmethodById(-2);
		}
		
		Set<Detectmethod> detectmethods = detectmethodDAO.findDetectmethodByName(detectmethodString);
		if(detectmethods.size() >0) {
			detectmethod = CmiSetUtil.getFirstInstance(detectmethods);
		}else {
			detectmethod = entityFactory.initDetectmethod();
			detectmethod.setName(detectmethodString);
			detectmethod.setStep("");
			detectmethod = detectmethodService.saveDetectmethod(detectmethod);
		}
		return detectmethod;
	}

private Address buildDiscoveryAddress(Event9zxl event9zxl) {
//	有省、市、县地址，先找县，再找市，再找省
	Set<Address> countyAddresss = addressDAO.findAddressByName(event9zxl.getDiscoverycounty());
	if(countyAddresss.size()>0) {
		return CmiSetUtil.getLastInstance(countyAddresss);
	}
	
	Set<Address> districtAddresss = addressDAO.findAddressByName(event9zxl.getDiscoverydistrict());
	if(districtAddresss.size()>0) {
		return CmiSetUtil.getLastInstance(districtAddresss);
	}
	
	Set<Address> provinceAddresss = addressDAO.findAddressByName(event9zxl.getSourceprovince());
	if(provinceAddresss.size()>0) {
		return CmiSetUtil.getLastInstance(provinceAddresss);
	}
	return null;
}

private User buildReportor(Event9zxl event9zxl) {
		User user = entityFactory.initUser();
//		来源是用户，可以包含监管机构、媒体报道等这种抽象的用户。
		Set<User> users = userDAO.findUserByName(event9zxl.getSource());
		if(users.size() > 0) {
			user = CmiSetUtil.getLastInstance(users);
		}else {
			user.setName(event9zxl.getSource());
			user.setUsername(event9zxl.getSource());
			user.setPassword("askfjqej;askdfjpij;nvaeriifjwertjmdsgfwqert234");
			user = userService.saveUser(user);
		}
		return user;
	}

private Detectmethod buildDetectmethod(Event9zxl event9zxl) {
		Detectmethod detectmethod = entityFactory.initDetectmethod(); 
		String detectmethodName = event9zxl.getDetectmethod();
		
		if(detectmethodName == null) {
			return null;
		}
		
		
		Set<Detectmethod> ds = detectmethodDAO.findDetectmethodByName(detectmethodName);
		if(ds.size() > 0) {
			detectmethod = CmiSetUtil.getLastInstance(ds);
		}else {
			detectmethod.setName(detectmethodName);
			detectmethod = detectmethodService.saveDetectmethod(detectmethod);
		}
		return detectmethod;
	}


	private Set<Foodbatchfiller> buildFoodbatchfiller(Event9zxl event9zxl) {
		Set<Foodbatchfiller> foodbatchfillers = new HashSet<Foodbatchfiller>();
		
		String foodbatcherfillerString = event9zxl.getFoodbatchfiller();
		if(foodbatcherfillerString == null) {
			return null;
		}
		
		String[] foodbatcherfillerStrings = foodbatcherfillerString.split("、");
		for(int i = 0; i< foodbatcherfillerStrings.length; i++) {
			Set<Foodbatchfiller> fs = foodbatchfillerDAO.findFoodbatchfillerByName(foodbatcherfillerStrings[i]);
			foodbatchfillers.addAll(foodbatchfillers);
		}
		return foodbatchfillers;
	}

	private Set<Adultertype> buildAdultertype(Event9zxl event9zxl) {
		Set<Adultertype> adultertypes = new HashSet<Adultertype>();
		String[] adultertypesString = event9zxl.getAdultertype().split("、");
		if(adultertypesString.length<1) {
			return null;
		}
		
		for(String adultertype: adultertypesString) {
			Set<Adultertype> as = adultertypeDAO.findAdultertypeByName(adultertype);
			if(as.size()>0) {
				adultertypes.addAll(as);
			}
		}
		return adultertypes;
	}

	private Eventadulterlink buildEventadulterlink(Event9zxl event9zxl) {
		Eventadulterlink eventadulterlink = entityFactory.initEventadulterlink();
		
		String adulterlinkName = event9zxl.getAdulterlink();
		Set<Adulterlink> adulterlinks = adulterlinkDAO.findAdulterlinkByName(adulterlinkName);
		Adulterlink adulterlink = null;
//		掺假环节也不能修改。这些环节是固定的。
		if(adulterlinks.size() >0) {
			adulterlink = CmiSetUtil.getLastInstance(adulterlinks);
		}else {
			adulterlink = adulterlinkDAO.findAdulterlinkById(-2);
		}
		eventadulterlink.setAdulterlink(adulterlink);
		return eventadulterlink;
	}

	private Eventpunish buildEventpunish(Event9zxl event9zxl) {
		Eventpunish eventpunish = null;
		String eventpunishString = event9zxl.getEventpunish();
		if(eventpunishString ==null || eventpunishString.trim().equals("") ) {
			return eventpunish;
		}
//		把“effect”中的内容作为eventpunish的描述来说明
		
		eventpunish = entityFactory.initEventpunish();
		eventpunish.setDescription(event9zxl.getEventpunish());
		return eventpunish;
	}

	
	private Address buildSourceAddress(Event9zxl event9zxl) {
//		有省、市、县地址，先找县，再找市，再找省
		Set<Address> countyAddresss = addressDAO.findAddressByName(event9zxl.getSourcecounty());
		if(countyAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(countyAddresss);
		}
		
		Set<Address> districtAddresss = addressDAO.findAddressByName(event9zxl.getSourcedistrict());
		if(districtAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(districtAddresss);
		}
		
		Set<Address> provinceAddresss = addressDAO.findAddressByName(event9zxl.getSourceprovince());
		if(provinceAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(provinceAddresss);
		}
		return null;
	}
	
	private Detect buildDetect(Event9zxl crawlerevent) {
		Detect detect = entityFactory.initDetect();
		return detect;
	}

	private Detectdetail buildDetectdetail(Event9zxl enent9zxl) {
		Detectdetail instance = entityFactory.initDetectdetail();//CmiSetUtil.getSoleInstance(detectdetailDAO.findDetectdetailByName(enent9zwz.getDetectdetail()));
		return instance;
	}


//	没有食物批次，对每一个事件创建一个只适用于链接的食物。食物批次添加一个是否真实的食物批次。
	private Foodbatch buildFoodbatch(Event9zxl enent9zxl) {
		Foodbatch foodbatch = entityFactory.initFoodbatch();
		return foodbatch;
	}

	private Food buildFood(Event9zxl event9xls) {
		
		String foodName = event9xls.getFood();
		if(foodName == null || foodName.trim().equals("")) {
			return null;
		}
//		Food food = entityFactory.initFood();
		Set<Food> foodsByName = new HashSet<Food>();
		
		String producerName = event9xls.getProducer();
		
//		生产商：如果excel中不存在，
		Producer producer = null;
		if(!( producerName == null || producerName.trim().equals(""))) {
//			生产商名称唯一
			Set<Producer> producers = producerDAO.findProducerByName(event9xls.getProducer());
			if(producers.size()>0) {
				producer = CmiSetUtil.getFirstInstance(producers);			
				
				Set<Food> fs = cmiFoodDAO.findFoodsByNameAndProducer(foodName, producer.getName());
				if(fs.size()>0) {
					return CmiSetUtil.getFirstInstance(fs);
				}
				Food food = entityFactory.initFood();
				food.setName(foodName);
				food.setProducer(producer);
				food = foodService.saveFood(food);
				return food;
			}else {
				producer = entityFactory.initProducer();
				producer.setName(producerName);
				producer = producerService.saveProducer(producer);
				
				Food food = entityFactory.initFood();
				food.setName(foodName);
				food.setProducer(producer);
				food = foodService.saveFood(food);
				return food;
			}
		}else {
//			
//			食物名称查找食物，可能有多个，对每一个进行地址匹配，
			foodsByName = foodDAO.findFoodByName(foodName);
			if(foodsByName.size()==0) {
				Food food = entityFactory.initFood();
				food.setName(foodName);
				food = foodService.saveFood(food);
				return food;
			}			
			
			for (Food foodByName : foodsByName) {
//				估计是懒加载的原有，不能获取本次导入请求过程中添加的foodbatch，因此，通过foodbatchDAO的方式获取
//				Set<Foodbatch> foodbatchs = foodByName.getFoodbatchsForFood();
				Set<Foodbatch> foodbatchs = foodbatchDAO.findFoodbatchsByFood(foodByName.getId(), -1, -1);
				
				for (Foodbatch foodbatch : foodbatchs) {
//					每个食物批次有多个事件
//					Set<Event> events = foodbatch.getEventsForFoodbatch();
					Set<Event> events = eventDAO.findEventsByFoodbatch(foodbatch.getId(), -1, -1);
					
					for (Event event : events) {
//						每个事件地址。事件来源地址为空，保持到数据库中是-2；
//						TODO 待解决，纯净水没有厂商、来源地、发现地导致多个food的记录缺陷原因：
//						因为数据库中没有地址用的id为-2的地址代替，而电子表格中是空字符串
						
						String eventSourceAddressName = event.getSourceAddress().getName();
						String eventDiscoveryAddressName = event.getDiscoveryAddress().getName();
//						******确定来源地址，
						String xlsSourceAddress = "";
						String xlsCounty = event9xls.getSourcecounty().trim();
						String xlsDistrict = event9xls.getSourcedistrict().trim();
						String xlsProvince = event9xls.getSourceprovince().trim();
						
						if(!xlsCounty.equals("")) {
							xlsSourceAddress = xlsCounty;
						}else if(!xlsDistrict.equals("")) {
							xlsSourceAddress = xlsDistrict;
						}else if(!xlsProvince.equals("")) {
							xlsSourceAddress = xlsProvince;
						}

//						******确定发现地址
						String xlsDiscoveryAddress = "";
						String xlsDiscoveryCounty = event9xls.getDiscoverycounty().trim();
						String xlsDiscoveryDistrict = event9xls.getDiscoverydistrict().trim();
						String xlsDiscoveryProvince = event9xls.getDiscoveryprovince().trim();
						
						if(!xlsDiscoveryCounty.equals("")) {
							xlsDiscoveryAddress = xlsDiscoveryCounty;
						}else if(!xlsDiscoveryDistrict.equals("")) {
							xlsDiscoveryAddress = xlsDiscoveryDistrict;
						}else if(!xlsDiscoveryProvince.equals("")) {
							xlsDiscoveryAddress = xlsDiscoveryProvince;
						}
	

//						(1) 待入库的事件有来源地址
						if(!xlsSourceAddress.equals("")) {
//							有来源地址
							if(eventSourceAddressName.equals(xlsSourceAddress)) {
								return foodByName;
							}
//						(2) 待入库的事件没有发现地址
						}else {
//							（2.1）待入库的事件有发现地址
							if(!xlsDiscoveryAddress.equals("")) {
								if(eventDiscoveryAddressName.equals(xlsDiscoveryAddress)) {
									return foodByName;
								}
//							（2.2）待入库的事件没有发现地址
							}else {
								if(event.getDiscoveryAddress().getId() == -2) {
									return foodByName;
								}
							}
						}
					}					
				}
			}		
		}
	
//		没有还没有返回，表示没有找到食物，新建一个食物
		Food food = entityFactory.initFood();
		food.setName(foodName);
		food = foodService.saveFood(food);
//		if(food.getId()==null) {
////			有可能出现：食物名称相同，因为物理主键的原因，不能保存数据的情况。
//			
//		}		

		return food;
	}

// 获取精确的类型，如果没有找到就使用著类型，如果都为空，就返回-2的那个类型
	private Foodtype buildFoodtype(Event9zxl enent9zwz) {
		Foodtype foodtype = null;
		String maintypeString = enent9zwz.getFoodmaintype();
		if(maintypeString == null || maintypeString.trim().equals("")) {
			String subtypeString = enent9zwz.getFoodsubtype();
			if(subtypeString == null || subtypeString.trim().equals("")) {
				foodtype = foodtypeDAO.findFoodtypeById(-2);
			}else {
				Set<Foodtype> foodtypes = foodtypeDAO.findFoodtypeByName(subtypeString);
				if(foodtypes.size()>0) {
					foodtype = CmiSetUtil.getFirstInstance(foodtypes);
				}else {
					foodtype = foodtypeDAO.findFoodtypeById(-2);
				}
			}
		}else {
			Set<Foodtype> foodtypes = foodtypeDAO.findFoodtypeByName(maintypeString);
			if(foodtypes.size()>0) {
				foodtype = CmiSetUtil.getFirstInstance(foodtypes);
			}else {
				foodtype = foodtypeDAO.findFoodtypeById(-2);
			}
		}
		return foodtype;
	}

//	来源地点更像主体。
	private Subject buildSubject(Event9zxl enent9zwz) {
		if(enent9zwz.getSubject() == null) { 
			return null; 
		}
		 
		Subject subject = CmiSetUtil.getSoleInstance(subjectDAO.findSubjectByName(enent9zwz.getSubject())); 
		if(subject == null) { 
			subject = entityFactory.initSubject(); 
			subject.setName(enent9zwz.getSubject());
			subject = subjectService.saveSubject(subject);
		}
		return subject;
	}
}